import { error, warning } from '@web-utils/core'
import { findParent } from '@/util/index'
import { httpPost } from '@/http'

export const log =
  process.env.VUE_APP_ERROR_DETECT === 'Y'
    ? ({ url, message, errorType }) =>
        httpPost('https://10.1.10.22/error-detector/log', {
          url,
          message,
          errorType
        })
    : () => Promise.resolve(true)

const is = (value, type) => Object.prototype.toString.call(value) === `[object ${type}]`
const isError = value => is(value, 'Error')
const isNumber = value => is(value, 'Number')
const isString = value => is(value, 'String')
const isPlainObject = value => is(value, 'Object')
const isArray = value => is(value, 'Array')

function getErrorMessage(e) {
  if (isString(e)) {
    return e
  } else if (isPlainObject(e) || isArray(e)) {
    return JSON.stringify(e)
  } else if (isError(e)) {
    return e.stack
  } else if (isNumber(e)) {
    return e
  } else {
    return Object.prototype.toString.call(e)
  }
}

export const userErrorDetector = Vue => {
  const isDev = process.env.NODE_ENV === 'development'
  const reserveComps = ['FormView', 'Toolbar', 'ToolbarButton']

  Vue.config.errorHandler = function (e, vm) {
    const message = getErrorMessage(e)
    error.call(
      isDev ? findParent(vm, vm => reserveComps.includes(vm.$options.name)) : null,
      isDev ? e : e?.message || e
    )
    log({ url: window.location.hash, message, errorType: 'error:vue' }).catch()
  }
  Vue.config.warnHandler = function (msg, vm) {
    const message = getErrorMessage(msg)
    warning.call(isDev ? findParent(vm, vm => reserveComps.includes(vm.$options.name)) : null, message)
    log({ url: window.location.hash, message, errorType: 'warn:vue' }).catch()
  }
  window.addEventListener('error', e => {
    const message = getErrorMessage(e.error)
    log({ url: window.location.hash, message, errorType: 'error' }).catch()
  })

  window.addEventListener('unhandledrejection', e => {
    const message = getErrorMessage(e.reason)
    log({ url: window.location.hash, message, errorType: 'unhandledrejection' }).catch()
  })
}
